 /** 
  * @see https://github.com/hongru/Laro  author hongru
  */
 qinglan.Canvas.Class = (function() {
 	var context = this;
 	var f = 'function';
 	var fnTest =  /xyz;/.test(function() {xyz;}) ? /\bsupr\b/ : /.*/;
 	var proto = 'prototype';
 	var isFunction = qinglan.Type.isFunction;

 	var Class = function(o) {
 			return extend.call(isFunction(o) ? o : function() {}, o, 1);
 		};


 	var wrap = function(k, fn, supr) {
 			return function() {
 				var tmp = this.supr;
 				this.supr = supr[proto][k];
 				var ret = fn.apply(this, arguments);
 				this.supr = tmp;
 				return ret;
 			};
 		};

 	var process = function(what, o, supr) {
 			for (var k in o) {
 				if (o.hasOwnProperty(k)) {
 					what[k] = isFunction(o[k]) && isFunction(supr[proto][k]) && fnTest.test(o[k]) ? wrap(k, o[k], supr) : o[k];
 				}
 			}
 		};

 	function extend(o, fromSub) {
 		// must redefine noop each time so it doesn't inherit from previous arbitrary classes
 		var noop = function() {};
 		noop[proto] = this[proto];
 		var supr = this;
 		var prototype = new noop();
 		var isFn = isFunction(o);
 		var _constructor = isFn ? o : this;
 		var _methods = isFn ? {} : o;

 		function fn() {
 			if (this.initialize) this.initialize.apply(this, arguments);
 			else {
 				fromSub || isFn && supr.apply(this, arguments);
 				_constructor.apply(this, arguments);
 			}
 		}

 		fn.methods = function(o) {
 			process(prototype, o, supr);
 			fn[proto] = prototype;
 			return this;
 		};

 		fn.methods.call(fn, _methods).prototype.constructor = fn;

 		fn.extend = arguments.callee;
 		fn[proto].implement = fn.statics = function(o, optFn) {
 			o = typeof o == 'string' ? (function() {
 				var obj = {};
 				obj[o] = optFn;
 				return obj;
 			}()) : o;
 			process(this, o, supr);
 			return this;
 		};

 		return fn;
 	}
 	/**
 	 * noConflict
 	 */
 	Class.noConflict = function() {
 		context.Class = old;
 		return this;
 	};
 	context.Class = Class;

 	return Class;
 })(window, undefined);
